/*
 * Copyright (c) 2009 Robert Esser
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.e2ser.util;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;

import net.e2ser.PNBrowser;
import net.e2ser.R;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;

/**
 * @author Rob Esser
 * @version 10/8/2009
 * 
 */
public class FileChooser extends Activity {

  /**
   * Type value indicating that the <code>FileChooser</code> supports an "Open"
   * file operation.
   */
  public static final int OPEN_FILE_CHOOSER = 0;

  /**
   * Type value indicating that the <code>FileChooser</code> supports a "Save"
   * file operation.
   */
  public static final int SAVE__FILE_CHOOSER = 1;

  public static final String FILENAME = "FILENAME";
  public static final String DIRNAME = "DIRNAME";

  public static final String MODE = "MODE";

  private Button okButton;
  private Button cancelButton;
  private EditText fileNameEditText;
  private ListView fileListView;

  private File currentDirectory = null;
  private File selectedFile = null;

  private SimpleAdapter listAdapter = null;
  private ArrayList<HashMap<String, Object>> fileListData = new ArrayList<HashMap<String, Object>>();

  private File[] files = null;

  private int mode;

  private int lastPosition = -1;

  /**
   * @see android.app.Dialog#onCreate(android.os.Bundle)
   */
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Bundle extras = getIntent().getExtras();
    if (extras != null) {
      if (extras.getInt(MODE, OPEN_FILE_CHOOSER) == OPEN_FILE_CHOOSER) {
        mode = OPEN_FILE_CHOOSER;
      } else if (extras.getInt(MODE, OPEN_FILE_CHOOSER) == SAVE__FILE_CHOOSER) {
        mode = SAVE__FILE_CHOOSER;
      }
    }
    //Log.v(PNBrowser.TAG, "FileChooser: Dialog created");
    if (mode == SAVE__FILE_CHOOSER) {
      setContentView(R.layout.filechooser);
    } else {
      setContentView(R.layout.filechooseropen);
    }
    
    okButton = (Button) findViewById(R.id.okButton);
    cancelButton = (Button) findViewById(R.id.cancelButton);
    fileNameEditText = (EditText) findViewById(R.id.fileNameEditText);
    fileListView = (ListView) findViewById(R.id.fileListView);
    fillFileList();
    String fn = extras.getString(FILENAME);
    if (fn != null) {
      fileNameEditText.setText(fn);
    }
   // Now create an adapter and set it to display using our row
    fileListView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
      public void onItemSelected(AdapterView<?> parentView, View childView, int position, long id) {
        setFileListSelected(position);
      }

      public void onNothingSelected(AdapterView<?> parentView) {
        setFileListSelected(-1);
      }
    });
    okButton.setOnClickListener(okButtonListener);
    cancelButton.setOnClickListener(cancelButtonListener);
  }

  /**
   * Rebuild the file list - This could be improved...
   */
  private void fillFileList() {
    if (currentDirectory == null) {
      currentDirectory = getBaseContext().getFilesDir();
    }

    Log.v(PNBrowser.TAG, "File Chooser directory: " + currentDirectory.getAbsolutePath());
    if (currentDirectory.getAbsolutePath().equals(getBaseContext().getFilesDir().getAbsolutePath())) {
      // I am the root user directory
      files = currentDirectory.listFiles();
    } else {
      // add in parent directory
      File[] tmpFiles = currentDirectory.listFiles();
      files = new File[tmpFiles.length + 1];
      files[0] = new File("..");
      for (int i = 0; i < tmpFiles.length; i++) {
        files[i + 1] = tmpFiles[i];
      }
    }

    // first empty data
    while (!fileListData.isEmpty()) {
      fileListData.remove(fileListData.size() - 1);
    }

    for (int i = 0; i < files.length; i++) {
      HashMap<String, Object> map = new HashMap<String, Object>();
      map.put("Image", files[i].isDirectory() ? new Integer(R.drawable.dir) : new Integer(R.drawable.file));
      map.put("File", files[i].getName());
      fileListData.add(map);
    }
    String[] from = new String[] { "Image", "File" };

    int[] to = new int[] { R.id.imageView, R.id.textView };
    if (listAdapter == null) {
      listAdapter = new SimpleAdapter(getBaseContext(), fileListData, R.layout.filechooserlistviewrow, from, to);
      fileListView.setAdapter(listAdapter);
    } else {
      // notify that data has changed
      listAdapter.notifyDataSetChanged();
    }
  }

  private void setFileListSelected(int i) {
    Log.v(PNBrowser.TAG, "FileChooser: file selected: " + i + " " + (i >= 0 ? files[i].toString() : "<>"));
    if (i >= 0) {
      // we have a valid selection so see if it is a directory and enter it
      if (files[i].isDirectory()) {
        currentDirectory = files[i];
        fillFileList();
        lastPosition = -1;
      } else {
        if (fileNameEditText != null) {
          fileNameEditText.setText(files[i].getName());
        }
        lastPosition = i;
      }
    }
  }

  private OnClickListener okButtonListener = new OnClickListener() {
    public void onClick(View v) {
      if (v.isEnabled()) {
        // user code here
        int i = lastPosition; // fileListView.getSelectedItemPosition();
        if (i >= 0) {
          // we have a valid selection so see if it is a directory and enter it
          if (files[i].isDirectory()) {
            currentDirectory = files[i];
            setFile(null);
          } else {
            // its a file
            setFile(files[i]);
          }
        } else {
          setFile(null);
        }

        Bundle bundle = new Bundle();
        String filename = "";
        String dirname = "";
        File file = getFile();
        if (file != null) {
          filename = file.getName();
          file = file.getParentFile();
          if (file != null) {
            dirname = file.getParentFile().getAbsolutePath();
          }
        }
        bundle.putString(FileChooser.FILENAME, filename);
        bundle.putString(FileChooser.DIRNAME, dirname);
        Intent mIntent = new Intent();
        mIntent.putExtras(bundle);
        setResult(Activity.RESULT_OK, mIntent);
        finish();
      }
    }
  };

  private OnClickListener cancelButtonListener = new OnClickListener() {
    public void onClick(View v) {
      if (v.isEnabled()) {
        // user code here
        Bundle bundle = new Bundle();
        Intent mIntent = new Intent();
        mIntent.putExtras(bundle);
        setResult(Activity.RESULT_OK, mIntent);
        finish();
      }
    }
  };

  public void setFile(File file) {
    Log.v(PNBrowser.TAG, "FileChooser: setFile: " + (file == null ? "null" : file.toString()));
    selectedFile = file;
  }

  public File getFile() {
    if (mode == OPEN_FILE_CHOOSER) {
      return selectedFile;
    } else {
      String editText = fileNameEditText.getText().toString().trim();
      if (editText.length() == 0) {
        // nothing entered
        return null;
      } else {
        return new File(currentDirectory, editText);
      }
    }
  }

  /**
   * Returns the selected file. This can be set either by the programmer via
   * <code>setFile</code> or by a user action, such as either typing the
   * filename into the UI or selecting the file from a list in the UI.
   * 
   * @see #setSelectedFile
   * @return the selected file
   */
  public File getSelectedFile() {
    return selectedFile;
  }

}
